﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System.Collections.Generic;
using ScrumTable.Common;
using ScrumTable.Common.Collections;
using ScrumTable.Common.Data;
using ScrumTable.DL.Data.Generic.Cache;
using ScrumTable.DL.Data.Schema.ScrumTableV1;

#endregion


namespace ScrumTable.DL.Data.Local
{
    /// <summary>
    /// Provides an interface for the basic data provider.
    /// </summary>
    public class BaseDataProvider : IBaseDataProvider
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private readonly CacheFieldDefinition _userStoryNameField;
        private readonly CacheFieldDefinition _userStoryDescriptionField;
        private readonly CacheFieldDefinition _userStoryRankingField;
        private readonly CacheFieldDefinition _userStoryStoryPointsField;
        private readonly CacheFieldDefinition _userStoryStateField;
        private readonly CacheFieldDefinition _userStoryMemberIdField;

        private readonly CacheFieldDefinition _taskNameField;
        private readonly CacheFieldDefinition _taskDescriptionField;
        private readonly CacheFieldDefinition _taskEstimateField;
        private readonly CacheFieldDefinition _taskPriorityField;
        private readonly CacheFieldDefinition _taskStackRankField;
        private readonly CacheFieldDefinition _taskRemainingWorkField;
        private readonly CacheFieldDefinition _taskStateField;
        private readonly CacheFieldDefinition _taskMemberIdField;
        private readonly CacheFieldDefinition _taskCompletedWorkField;

        private readonly CacheFieldDefinition _bugNameField;
        private readonly CacheFieldDefinition _bugDescriptionField;
        private readonly CacheFieldDefinition _bugSeverityField;
        private readonly CacheFieldDefinition _bugStackRankField;
        private readonly CacheFieldDefinition _bugStateField;
        private readonly CacheFieldDefinition _bugMemberIdField;

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        /// <summary>
        /// Gets the workitem definitions which are used to initialize the data
        /// driver.
        /// </summary>
        public IEnumerable<CacheWorkItemType> WorkItemTypes { get { return new[] { TaskType, UserStoryType, BugType }; } }

        /// <summary>
        /// Gets the user story type with a set of default cache field definitions.
        /// </summary>
        public CacheWorkItemType UserStoryType { get; private set; }

        /// <summary>
        /// Gets the task type with a set of default cache field definitions.
        /// </summary>
        public CacheWorkItemType TaskType { get; private set; }

        /// <summary>
        /// Gets the bug type with a set of default cache field definitions.
        /// </summary>
        public CacheWorkItemType BugType { get; private set; }

        /// <summary>
        /// Gets the members associated to the current field definition set.
        /// </summary>
        public IEnumerable<CacheMember> Members { get; private set; }

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new BaseDataProvider instance.
        /// </summary>
        public BaseDataProvider(CacheContext context, IEnumerable<CacheMember> members)
        {
            PreCondition.AssertNotNull(context, "context");
            PreCondition.AssertNotNull(members, "members");

            CacheElementFactory elementFactory = context.ElementFactory;
            ScrumTableV1Schema schema = context.Schema;

            Members = members;

            //----------------------------------------------------------------
            // Create Field Definition Instances
            //----------------------------------------------------------------

            _userStoryNameField = elementFactory.CreateFieldDefinition(
                0, schema.UserStorySchema.Name.SchemaDisplayName, schema.UserStorySchema.Name,
                DataType.PlainText, new object[0]);
            _userStoryDescriptionField = elementFactory.CreateFieldDefinition(
                1, schema.UserStorySchema.Description.SchemaDisplayName, schema.UserStorySchema.Description,
                DataType.PlainText, new object[0]);
            _userStoryStateField = elementFactory.CreateFieldDefinition(
                3, schema.UserStorySchema.State.SchemaDisplayName, schema.UserStorySchema.State,
                DataType.PlainText, new[] { "Active", "InProgress", "Resolved", "Closed" }, "Active");
            _userStoryMemberIdField = elementFactory.CreateFieldDefinition(
                4, schema.UserStorySchema.MemberId.SchemaDisplayName, schema.UserStorySchema.MemberId,
                DataType.PlainText, Members.ToArray(m => m.ReferenceName));
            _userStoryRankingField = elementFactory.CreateFieldDefinition(
                5, schema.UserStorySchema.Ranking.SchemaDisplayName, schema.UserStorySchema.Ranking,
                DataType.Double, new object[0]);
            _userStoryStoryPointsField = elementFactory.CreateFieldDefinition(
                6, schema.UserStorySchema.StoryPoints.SchemaDisplayName, schema.UserStorySchema.StoryPoints,
                DataType.Double, new object[0]);

            _taskNameField = elementFactory.CreateFieldDefinition(
                10, schema.TaskSchema.Name.SchemaDisplayName, schema.TaskSchema.Name,
                DataType.PlainText, new object[0]);
            _taskDescriptionField = elementFactory.CreateFieldDefinition(
                11, schema.TaskSchema.Description.SchemaDisplayName, schema.TaskSchema.Description,
                DataType.PlainText, new object[0]);
            _taskStateField = elementFactory.CreateFieldDefinition(
                12, schema.TaskSchema.State.SchemaDisplayName, schema.TaskSchema.State,
                DataType.PlainText, new[] { "Active", "InProgress", "Closed" }, "Active");
            _taskMemberIdField = elementFactory.CreateFieldDefinition(
                13, schema.TaskSchema.MemberId.SchemaDisplayName, schema.TaskSchema.MemberId,
                DataType.PlainText, Members.ToArray(m => m.ReferenceName));
            _taskEstimateField = elementFactory.CreateFieldDefinition(
                14, schema.TaskSchema.Estimate.SchemaDisplayName, schema.TaskSchema.Estimate,
                DataType.Double, new object[0]);
            _taskPriorityField = elementFactory.CreateFieldDefinition(
                15, schema.TaskSchema.Priority.SchemaDisplayName, schema.TaskSchema.Priority,
                DataType.Integer, new object[] { 1, 2, 3, 4 }, 2);
            _taskStackRankField = elementFactory.CreateFieldDefinition(
                16, schema.TaskSchema.Ranking.SchemaDisplayName, schema.TaskSchema.Ranking,
                DataType.Double, new object[0]);
            _taskRemainingWorkField = elementFactory.CreateFieldDefinition(
                17, schema.TaskSchema.RemainingWork.SchemaDisplayName, schema.TaskSchema.RemainingWork,
                DataType.Double, new object[0]);
            _taskCompletedWorkField = elementFactory.CreateFieldDefinition(
                18, schema.TaskSchema.CompletedWork.SchemaDisplayName, schema.TaskSchema.CompletedWork,
                DataType.Double, new object[0]);

            _bugNameField = elementFactory.CreateFieldDefinition(
                20, schema.BugSchema.Name.SchemaDisplayName, schema.BugSchema.Name,
                DataType.PlainText, new object[0]);
            _bugDescriptionField = elementFactory.CreateFieldDefinition(
                21, schema.BugSchema.Description.SchemaDisplayName, schema.BugSchema.Description,
                DataType.Html, new object[0]);
            _bugStateField = elementFactory.CreateFieldDefinition(
                22, schema.BugSchema.State.SchemaDisplayName, schema.BugSchema.State,
                DataType.PlainText, new[] { "Active", "InProgress", "Resolved", "Closed" }, "Active");
            _bugMemberIdField = elementFactory.CreateFieldDefinition(
                23, schema.BugSchema.MemberId.SchemaDisplayName, schema.BugSchema.MemberId,
                DataType.PlainText, Members.ToArray(m => m.ReferenceName));
            _bugSeverityField = elementFactory.CreateFieldDefinition(
                24, schema.BugSchema.Severity.SchemaDisplayName, schema.BugSchema.Severity,
                DataType.PlainText, new[] { "Critical", "High", "Medium", "Low" }, "Medium");
            _bugStackRankField = elementFactory.CreateFieldDefinition(
                25, schema.BugSchema.Ranking.SchemaDisplayName, schema.BugSchema.Ranking,
                DataType.Double, new object[0]);

            //----------------------------------------------------------------
            // Create Work Item Type Instances
            //----------------------------------------------------------------

            UserStoryType = elementFactory.CreateWorkItemType(
                schema.UserStorySchema.SchemaMappedName,
                schema.UserStorySchema,
                new[]
                    {
                        _userStoryNameField,
                        _userStoryDescriptionField,
                        _userStoryRankingField,
                        _userStoryStoryPointsField,
                        _userStoryStateField,
                        _userStoryMemberIdField
                    },
                elementFactory.CreateWorkflow(
                    elementFactory.CreateTransitions(_userStoryStateField.AllowedValues),
                    schema.UserStorySchema.State, false));

            TaskType = elementFactory.CreateWorkItemType(
                schema.TaskSchema.SchemaMappedName,
                schema.TaskSchema,
                new[]
                    {
                        _taskNameField,
                        _taskDescriptionField,
                        _taskEstimateField,
                        _taskPriorityField,
                        _taskStackRankField,
                        _taskRemainingWorkField,
                        _taskStateField,
                        _taskMemberIdField,
                        _taskCompletedWorkField
                    },
                elementFactory.CreateWorkflow(
                    elementFactory.CreateTransitions(_taskStateField.AllowedValues),
                    schema.TaskSchema.State, false));

            BugType = elementFactory.CreateWorkItemType(
                schema.BugSchema.SchemaMappedName,
                schema.BugSchema,
                new[]
                    {
                        _bugNameField,
                        _bugDescriptionField,
                        _bugSeverityField,
                        _bugStackRankField,
                        _bugStateField,
                        _bugMemberIdField
                    },
                elementFactory.CreateWorkflow(
                    elementFactory.CreateTransitions(_bugStateField.AllowedValues),
                    schema.BugSchema.State, true));
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}